/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Utility;

import Client.Client;
import java.io.*;
import java.security.*;
import java.security.cert.CRLException;
import java.security.cert.X509CRL;
import java.util.Collections;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.crypto.MarshalException;
import javax.xml.crypto.dsig.*;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.KeyValue;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.bouncycastle.ocsp.*;
import org.bouncycastle.openssl.PEMWriter;
import org.bouncycastle.util.encoders.Base64;
import org.w3c.dom.*;
import org.xml.sax.InputSource;

public class XMLUtility {

    /*
     * Ritorno il contenuto dell'Object del digital signature
     * doc è il documento xml digital signature (XMLSignuature)
     */
    public static String getCertificatoString(Document doc) {


        String result=null;

        try { 
            if(doc!=null){
                // Get a list of all elements in the document
                NodeList list = doc.getElementsByTagName("*");
                System.out.println("\tXML ELEMENTI DEL FILE XML: ");
                for (int i=0; i<list.getLength(); i++) {
                    // Get element
                    Element element = (Element)list.item(i);
                    if(element.getNodeName().equals("Object")){
                        result = element.getTextContent();
                        System.out.println("\t"+element.getNodeName()+"\tvalue: "+element.getTextContent());
                    }        
                }
            } 
            else{
                System.err.print("Errore nel documento");
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }

        return result;

    }
    
    
    /*
     * Ritorno il valore di tag contenuto nel file xml
     */
    public static String getValueStringInXML(Document doc, String tag) {


        String result=null;

        try { 
            if(doc!=null){
                // Get a list of all elements in the document
                NodeList list = doc.getElementsByTagName("*");
                //System.out.println("XML Elements: ");
                for (int i=0; i<list.getLength(); i++) {
                    // Get element
                    Element element = (Element)list.item(i);
                    if(element.getNodeName().equals(tag)){
                        result = element.getTextContent();
                        //System.out.println(element.getNodeName()+"\tvalue: "+element.getTextContent());
                    }        
                }
            } 
            else{
                System.err.print("Errore nel documento");
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }

        return result;

    }
   
    /*
     * Genera un xml per mandare la richiesta in digital signature xml
     * Creo il file xml perchè poi lo firmo con digital signature
     * e mando la signature come parametro.
     * Una volta arrivata la signature devo estrarre l'Object e i parametri dall'object.

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <richiesta>
        <id>xxx</id>
        <tipo>xxx</tipo>
    </richiesta>

     */
    public static Document getDocumentIdTipo(String id, String tipo) {
 
          Document doc = null;
            
	  try {
 
		DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
 
		// root elements
		doc = docBuilder.newDocument();
		Element rootElement = doc.createElement("richiesta");
		doc.appendChild(rootElement);
               
 
		// id elements
		Element firstname = doc.createElement("id");
		firstname.appendChild(doc.createTextNode(id));
		rootElement.appendChild(firstname);
 
		// tipo elements
		Element lastname = doc.createElement("tipo");
		lastname.appendChild(doc.createTextNode(tipo));
		rootElement.appendChild(lastname);
 
 
	  } catch (ParserConfigurationException pce) {
		pce.printStackTrace();
	  }
          
          return doc;
	} 
    
/*
     * Genera un xml per mandare la richiesta in digital signature xml
     * Creo il file xml perchè poi lo firmo con digital signature
     * e mando la signature come parametro.
     * Una volta arrivata la signature devo estrarre l'Object e i parametri dall'object.

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <richiesta>
        <status>xxx</status>
    </richiesta>

     */
    public static Document getDocumentStatus(String status) {
 
          Document doc = null;
            
	  try {
 
		DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
 
		// root elements
		doc = docBuilder.newDocument();
		Element rootElement = doc.createElement("richiesta");
		doc.appendChild(rootElement);
               
 
		// id elements
		Element firstname = doc.createElement("status");
		firstname.appendChild(doc.createTextNode(status));
		rootElement.appendChild(firstname);
 
 
	  } catch (ParserConfigurationException pce) {
		pce.printStackTrace();
	  }
          
          return doc;
	}     
    
 /*
     * Genera un xml per mandare xml con il certificato
     * Creo il file xml perchè poi lo firmo con digital signature
     * e mando la signature come parametro.
     * Una volta arrivata la signature devo estrarre l'Object e i parametri dall'object.

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <richiesta>
        <pkcs10>xxx</pkcs10>
        <id>xxx</id>
        <tipo>xxx</tipo>
       <nome>xxx</nome> 
            String cognome, 
            String organizzazione, 
            String unita, 
            String paese, 
            String email
    </richiesta>

     */
    public static Document getDocumentPKCS10(String pkcs10, String username, String tipo,
     String nome,
     String cognome,
     String organizzazione,
     String unita,
     String paese,
     String email            
            ) {
 
          Document doc = null;
            
	  try {
 
		DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
 
		// root elements
		doc = docBuilder.newDocument();
		Element rootElement = doc.createElement("richiesta");
		doc.appendChild(rootElement);
               
 
		// certificato elements
		Element pkcs10_tag = doc.createElement("pkcs10");
		pkcs10_tag.appendChild(doc.createTextNode(pkcs10));
		rootElement.appendChild(pkcs10_tag);
                
		// certificato elements
		Element username_tag = doc.createElement("id");
		username_tag.appendChild(doc.createTextNode(username));
		rootElement.appendChild(username_tag);
                
		// certificato elements
		Element tipo_tag = doc.createElement("tipo");
		tipo_tag.appendChild(doc.createTextNode(tipo));
		rootElement.appendChild(tipo_tag);  
                
                //------------------------------------
		Element nome_tag = doc.createElement("nome");
		nome_tag.appendChild(doc.createTextNode(nome));
		rootElement.appendChild(nome_tag);  
                
		Element cognome_tag = doc.createElement("cognome");
		cognome_tag.appendChild(doc.createTextNode(cognome));
		rootElement.appendChild(cognome_tag);  
                
		Element organizzazione_tag = doc.createElement("organizzazione");
		organizzazione_tag.appendChild(doc.createTextNode(organizzazione));
		rootElement.appendChild(organizzazione_tag);  
                
		Element unita_tag = doc.createElement("unita");
		unita_tag.appendChild(doc.createTextNode(unita));
		rootElement.appendChild(unita_tag);  
                
		Element paese_tag = doc.createElement("paese");
		paese_tag.appendChild(doc.createTextNode(paese));
		rootElement.appendChild(paese_tag);  
                
		Element email_tag = doc.createElement("email");
		email_tag.appendChild(doc.createTextNode(email));
		rootElement.appendChild(email_tag);                  
 
                
                
	  } catch (ParserConfigurationException pce) {
		pce.printStackTrace();
	  }
          
          return doc;
	}  
    
    /*
     * Genera un xml per mandare xml con il certificato
     * Creo il file xml perchè poi lo firmo con digital signature
     * e mando la signature come parametro.
     * Una volta arrivata la signature devo estrarre l'Object e i parametri dall'object.

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <richiesta>
        <certificato>xxx</certificato>
    </richiesta>

     */
    public static Document getDocumentCertificato(String certificato) {
 
          Document doc = null;
            
	  try {
 
		DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
 
		// root elements
		doc = docBuilder.newDocument();
		Element rootElement = doc.createElement("richiesta");
		doc.appendChild(rootElement);
               
 
		// certificato elements
		Element firstname = doc.createElement("certificato");
		firstname.appendChild(doc.createTextNode(certificato));
		rootElement.appendChild(firstname);
 
	  } catch (ParserConfigurationException pce) {
		pce.printStackTrace();
	  }
          
          return doc;
	}     
    
    /*
     * Genera un xml per mandare xml con il serial number
     * Creo il file xml perchè poi lo firmo con digital signature
     * e mando la signature come parametro.
     * Una volta arrivata la signature devo estrarre l'Object e i parametri dall'object.

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <richiesta>
        <serialnumber>xxx</serialnumber>
    </richiesta>

     */
    public static Document getDocumentSerialNumber(String serialnumber) {
 
          Document doc = null;
            
	  try {
 
		DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
 
		// root elements
		doc = docBuilder.newDocument();
		Element rootElement = doc.createElement("richiesta");
		doc.appendChild(rootElement);
               
 
		// certificato elements
		Element firstname = doc.createElement("serialnumber");
		firstname.appendChild(doc.createTextNode(serialnumber));
		rootElement.appendChild(firstname);
 
	  } catch (ParserConfigurationException pce) {
		pce.printStackTrace();
	  }
          
          return doc;
	}         
    
  /*
     * Genera un xml per mandare la risposta in digital signature xml
     * Creo il file xml perchè poi lo firmo con digital signature
     * e mando la signature come parametro.
     * Una volta arrivata la signature devo estrarre l'Object e i parametri dall'object.

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <risposta>
        <status>xxx</status>        
    </risposta>

     */
    public static Document getDocumentRispostaInt(int status) {
 
          Document doc = null;
            
	  try {
 
		DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
 
		// root elements
		doc = docBuilder.newDocument();
		Element rootElement = doc.createElement("risposta");
		doc.appendChild(rootElement);
               
 
		// status elements
		Element firstname = doc.createElement("status");
		firstname.appendChild(doc.createTextNode(String.valueOf(status)));
		rootElement.appendChild(firstname);
 
 
	  } catch (ParserConfigurationException pce) {
		pce.printStackTrace();
	  }
          
          return doc;
	}     
    
    
      /*
     * Genera un xml per mandare la risposta in digital signature xml
     * Creo il file xml perchè poi lo firmo con digital signature
     * e mando la signature come parametro.
     * Una volta arrivata la signature devo estrarre l'Object e i parametri dall'object.

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <risposta>
        <status>xxx</status>        
    </risposta>

     */
    public static Document getDocumentRispostaCrl(X509CRL crl) {
 
          Document doc = null;
            
	  try {
 
		DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
 
		// root elements
		doc = docBuilder.newDocument();
		Element rootElement = doc.createElement("risposta");
		doc.appendChild(rootElement);
               
 
		// status elements
		Element firstname = doc.createElement("crl");
                byte[] certCoded = Base64.encode(crl.getEncoded());
                String strCrlCoded = new String(certCoded);
            
		firstname.appendChild(doc.createTextNode(strCrlCoded));
		rootElement.appendChild(firstname);
 
 
	  } catch (CRLException ex) {
            Logger.getLogger(XMLUtility.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ParserConfigurationException pce) {
		pce.printStackTrace();
	  }
          
          return doc;
	}     

    
    
     public static Document getDocumentRispostaOCSP(OCSPResp ocsp) {
 
          Document doc = null;
            
	  try {
 
		DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
 
		// root elements
		doc = docBuilder.newDocument();
		Element rootElement = doc.createElement("risposta");
		doc.appendChild(rootElement);
               
 
		// status elements
		Element firstname = doc.createElement("ocsp");
                byte[] certCoded = Base64.encode(ocsp.getEncoded());
                String strCrlCoded = new String(certCoded);
            
		firstname.appendChild(doc.createTextNode(strCrlCoded));
		rootElement.appendChild(firstname);
 
 
	  } catch (IOException ex) {
            Logger.getLogger(XMLUtility.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ParserConfigurationException pce) {
		pce.printStackTrace();
	  }
          
          return doc;
	}     

    
    
    
     
     
    
       /*
         * Stampa un file xml document
         */
        public static void printDocumentXML(Document doc){
            try {
                Transformer transformer = TransformerFactory.newInstance().newTransformer();
                transformer.setOutputProperty(OutputKeys.INDENT, "yes");

                //initialize StreamResult with File object to save to file
                StreamResult result2 = new StreamResult(new StringWriter());
                DOMSource source = new DOMSource(doc);
                transformer.transform(source, result2);

                String xmlString = result2.getWriter().toString();
                System.out.println(xmlString);
            } catch (TransformerException ex) {
                Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        
        /*
         * Firma il documento
         */
        public static Document firmaDocumento(Document doc, Key privKey, Key pubKey){
        try {
            // Instantiate the document to be signed.
            XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
            Reference ref = fac.newReference("http://www.w3.org/TR/xml-stylesheet",fac.newDigestMethod(DigestMethod.SHA1, null));
            SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS,(C14NMethodParameterSpec) null),fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null),            Collections.singletonList(ref));
            KeyInfoFactory kif = fac.getKeyInfoFactory();
            KeyValue kv = kif.newKeyValue((PublicKey) pubKey);
            KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv));            

            // Create a DOMSignContext and specify the RSA PrivateKey and
            // location of the resulting XMLSignature's parent element.
            DOMSignContext dsc = new DOMSignContext
                (privKey, doc.getDocumentElement());

            // Create the XMLSignature, but don't sign it yet.
            XMLSignature signature = fac.newXMLSignature(si, ki);

            // Marshal, generate, and sign the enveloped signature.
            signature.sign(dsc);
            
            
        } catch (MarshalException ex) {
            Logger.getLogger(XMLUtility.class.getName()).log(Level.SEVERE, null, ex);
        } catch (XMLSignatureException ex) {
            Logger.getLogger(XMLUtility.class.getName()).log(Level.SEVERE, null, ex);
        } catch (KeyException ex) {
            Logger.getLogger(XMLUtility.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(XMLUtility.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvalidAlgorithmParameterException ex) {
            Logger.getLogger(XMLUtility.class.getName()).log(Level.SEVERE, null, ex);
        }
        
            return doc;
        }
    
        
    /*
     * Trasforma una stringa xml in document
     */
public static Document fromXMLStringToDocument(String doc) {
     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
  Document document=null;
        DocumentBuilder builder;  
        try  
        {  
            builder = factory.newDocumentBuilder();  
  
            // Use String reader  
            document = builder.parse( new InputSource(  
                    new StringReader( doc ) ) );  
  
            TransformerFactory tranFactory = TransformerFactory.newInstance();  
            Transformer aTransformer = tranFactory.newTransformer();  
            Source src = new DOMSource( document );  
            Result dest = new StreamResult( new File( "xmlFileName.xml" ) );  
            aTransformer.transform( src, dest );  
        } catch (Exception e)  
        {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
   return document;
  }        

    /*
     * Genera un xml per mandare la richiesta in digital signature xml
     * Creo il file xml perchè poi lo firmo con digital signature
     * e mando la signature come parametro.
     * Una volta arrivata la signature devo estrarre l'Object e i parametri dall'object.

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <richiesta>        
        <nome>xxx</nome>
        <cognome>xxx</cognome> 
        <tipo>xxx</tipo>
        <pair>xxx</pair> 
    </richiesta>
    */
    public static Document getDocumentRinnovoCertificato(KeyPair pair, String nome, String cognome, int tipo) throws ParserConfigurationException {
        
        Document doc = null;
        
        try { 

            // converte in stringa il pair delle chiavi
            StringWriter sw = new StringWriter();
            PEMWriter pw = new PEMWriter(sw);
            pw.writeObject(pair);
            pw.flush();
            String pair_stringa = sw.toString();
            
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            
            // root elements
            doc = docBuilder.newDocument();
            Element rootElement = doc.createElement("richiesta");
            doc.appendChild(rootElement);               
            
            // username elements
            Element nome_tag = doc.createElement("nome");
            nome_tag.appendChild(doc.createTextNode(nome));
            rootElement.appendChild(nome_tag);   
            
            // username elements
            Element cognome_tag = doc.createElement("cognome");
            cognome_tag.appendChild(doc.createTextNode(cognome));
            rootElement.appendChild(cognome_tag);               

            // tipo elements
            Element tipo_element = doc.createElement("tipo");
            tipo_element.appendChild(doc.createTextNode(String.valueOf(tipo)));
            rootElement.appendChild(tipo_element);  
          
            // pair elements
            Element firstname = doc.createElement("pair");
            firstname.appendChild(doc.createTextNode(pair_stringa));
            rootElement.appendChild(firstname); 
            
        } catch (IOException ex) {
            Logger.getLogger(XMLUtility.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        return doc;
        
    }

            
}